package cn.lingyangwl.agile.pay.pay.process.refund;

import cn.lingyangwl.agile.pay.common.assembly.RefundAssembly;
import cn.lingyangwl.agile.pay.common.constants.PayCacheKey;
import cn.lingyangwl.agile.pay.common.service.RefundOrderService;
import cn.lingyangwl.agile.pay.pay.channel.AbstractRefundService;
import cn.lingyangwl.agile.pay.pay.channel.IRefundService;
import cn.lingyangwl.agile.pay.pay.model.bo.MchAppConfigContext;
import cn.lingyangwl.agile.pay.pay.model.rqrs.ChannelRetMsgExt;
import cn.lingyangwl.agile.pay.pay.service.ConfigContextQueryService;
import cn.lingyangwl.framework.core.response.Resp;
import cn.lingyangwl.framework.lock.manager.ILockManager;
import cn.lingyangwl.framework.lock.model.ILock;
import cn.lingyangwl.framework.tool.core.StringUtils;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import cn.lingyangwl.agile.pay.model.entity.RefundOrder;
import cn.lingyangwl.agile.pay.model.rqrs.pay.refund.RefundOrderQO;
import cn.lingyangwl.agile.pay.pay.process.ChannelRefundOrderProcess;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author shenguangyang
 */
@Slf4j
@Service
public class QueryRefundOrderProcess {
    @Resource
    private ConfigContextQueryService configContextQueryService;
    @Resource
    private ChannelRefundOrderProcess channelRefundOrderProcess;
    @Resource
    private ILockManager lockManager;
    @Resource
    private RefundOrderService refundOrderService;
    @Resource
    private RefundAssembly refundAssembly;

    /**
     * 查单接口
     */
    public Resp<?> getRefundOrder(RefundOrderQO rq) {
        if(StringUtils.isAllEmpty(rq.getMchRefundNo(), rq.getRefundOrderNo())){
            throw new BizException("mchRefundNo 和 refundOrderNo 不能同时为空");
        }
        RefundOrder refundOrder = refundOrderService.getMchOrder(rq.getMchNo(), rq.getMchRefundNo(), rq.getRefundOrderNo());
        if(refundOrder == null){
            return Resp.fail("订单不存在");
        }

        if (refundOrder.getStatus().equalsIgnoreCase(RefundOrder.STATE_SUCCESS)) {
            return Resp.ok(refundAssembly.toRefundOrderRS(refundOrder));
        }

        ILock lock = lockManager.getLock(PayCacheKey.PAY_GLOBAL_LOCK.formatKey(refundOrder.getPayOrderNo()));
        boolean tryLock = lock.tryLock(5, TimeUnit.SECONDS);
        if (!tryLock) {
            throw new BizException("该订单锁抢占超时, refundOrderId: {}, payOrderNo: {}",
                    refundOrder.getRefundOrderId(), refundOrder.getPayOrderNo());
        }
        String refundOrderNo = refundOrder.getRefundOrderId();
        try {
            // 查询支付接口是否存在
            IRefundService queryService = AbstractRefundService.getService(refundOrder.getIfCode());

            // 支付通道接口实现不存在
            if (queryService == null) {
                log.error("查询退款补单：{} interface not exists!", refundOrder.getIfCode());
                return Resp.fail("未实现支付接口 " + refundOrder.getIfCode());
            }

            // 查询出商户应用的配置信息
            MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(refundOrder.getMchNo(), refundOrder.getAppId());

            ChannelRetMsgExt channelRetMsgExt = queryService.query(refundOrder, mchAppConfigContext);
            if (channelRetMsgExt == null) {
                log.error("查询退款补单：channelRetMsg is null");
                return Resp.fail("渠道响应结果为空");
            }

            log.info("查询退款补单：[{}]查询结果为：{}", refundOrderNo, JSON.toJSONString(channelRetMsgExt));
            // 根据渠道返回结果，处理退款订单
            channelRefundOrderProcess.handleRefundOrder4Channel(channelRetMsgExt, refundOrder);
            return Resp.ok(refundAssembly.toRefundOrderRS(refundOrderService.getById(refundOrderNo)));
        } catch (Exception e) {  // 继续下一次迭代查询
            log.error("查询退款补单：error refundOrderNo = {}", refundOrder.getRefundOrderId(), e);
            return Resp.fail(e.getMessage());
        } finally {
            lock.unlock();
        }
    }
}
